package cn.kgc.springday01.factory;

import cn.kgc.springday01.annotations.AutoWired;
import cn.kgc.springday01.dao.StudentDao;
import cn.kgc.springday01.dao.UserDao;
import cn.kgc.springday01.dao.impl.StudentDaoImpl;
import cn.kgc.springday01.dao.impl.UserDaoImpl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * @Author: 课工场
 * @Version: v1.0  2023/6/10
 * @Description:  工厂对象   23中设计模式 利用工厂模式  解决代码耦合问题
 *
 */
public class BeanFactory {

  private static Map<String,Object> map = new HashMap<>();

    static {
        // 初始化对象
        ResourceBundle bean = ResourceBundle.getBundle("bean");
        Set<String> keySet = bean.keySet();

        for (String key : keySet) {
            String className = bean.getString(key);
            try {
                Class<?> clazz = Class.forName(className);
                // 获取无参构造
                Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();
                // 创建对象
                Object o = declaredConstructor.newInstance();
                // 将对象存入 map
                map.put(key,o);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //  2. 初始化对象中的属性
        for (String key : keySet) {
            String className = bean.getString(key);
            try {
                Class<?> clazz = Class.forName(className);
                //  获取当前类对象的属性
                Field[] declaredFields = clazz.getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    AutoWired annotation = declaredField.getAnnotation(AutoWired.class);
                    if (annotation!=null){  //  赋值
                        Object o = map.get(key);
                        // 获取属性的名字  userDao
                        String name = declaredField.getName();
                        Object o1 = map.get(name);  //  userDao
                        // 提升操作权限   被private修饰的属性不能直接通过反射赋值
                        declaredField.setAccessible(true);
                        declaredField.set(o,o1);
                    }

                }

            } catch (Exception e) {
                e.printStackTrace();
            }


        }


    }

    public static UserDao getUserDao(){
        return new UserDaoImpl();
        //return new NewUserDaoImpl();
    }

    public static StudentDao getStudentDao(){
        return new StudentDaoImpl();

    }

    // 反射
    //public static Object getBean(Class clazz){
    //    try {
    //        //根据类对象 获取无参构造
    //        Constructor declaredConstructor = clazz.getDeclaredConstructor();
    //        Object o = declaredConstructor.newInstance();
    //        return o;
    //    } catch (Exception e) {
    //        e.printStackTrace();
    //    }
    //    return  null;
    //}

    // 反射 + 泛型
    //public static <T> T getBean(Class<T> clazz){
    //
    //    return  null;
    //}


    // 反射
    public static Object getBean(String beanName){
        return  map.get(beanName);
    }


    public static <T> T getBean(String beanName,Class<T> clazz){
        return (T) map.get(beanName);
    }
}
